Combine two paths with a path separator. If the second path starts
with a path separator or a drive letter, then it returns the second.
The intention is that
readFile (dir </> file)
will access the same file as
setCurrentDirectory dir; readFile
file.
Posix: "/directory" </> "file.ext" == "/directory/file.ext"
Windows: "/directory" </> "file.ext" == "/directory\\file.ext"
"directory" </> "/file.ext" == "/file.ext"
Valid x => (takeDirectory x </> takeFileName x) `equalFilePath` x
Combined:
Posix: "/" </> "test" == "/test"
Posix: "home" </> "bob" == "home/bob"
Posix: "x:" </> "foo" == "x:/foo"
Windows: "C:\\foo" </> "bar" == "C:\\foo\\bar"
Windows: "home" </> "bob" == "home\\bob"
Not combined:
Posix: "home" </> "/bob" == "/bob"
Windows: "home" </> "C:\\bob" == "C:\\bob"
Not combined (tricky):
On Windows, if a filepath starts with a single slash, it is relative
to the root of the current drive. In [1], this is (confusingly)
referred to as an absolute path. The current behavior of
</> is to never combine these forms.
Windows: "home" </> "/bob" == "/bob"
Windows: "home" </> "\\bob" == "\\bob"
Windows: "C:\\home" </> "\\bob" == "\\bob"
On Windows, from [1]: "If a file name begins with only a disk
designator but not the backslash after the colon, it is interpreted as
a relative path to the current directory on the drive with the
specified letter." The current behavior of
</> is to
never combine these forms.
Windows: "D:\\foo" </> "C:bar" == "C:bar"
Windows: "C:\\foo" </> "C:bar" == "C:bar"